home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / swagg_m.zip / GRAPHICS.SWG / 0105_Coordinate Systems.pas < prev    next >
Pascal/Delphi Source File  |  1994-08-24  |  9KB  |  290 lines

  1. {
  2.  -=> Quoting Sean Graham to All on 22 Jun 94 <=-
  3.  SG> some  (efficient, I would hope) code in pascal that will allow me to
  4.  SG> move in a 2D or  3D 'universe' (or more correctly, grid-system). Let me
  5.  
  6.  SG> Let's start out easy.  For example, how would I write code to draw a
  7.  SG> line on  a 50x80 (yes, ascii chars) screen from pos A(10,5) to pos
  8.  SG> B(47,56)?
  9.  SG> Now imagine that my screen has magically grown a third dimention.  So
  10.  SG> I now  want to draw a line from pos A(47,34,7) to pos B(21,11,33).  How
  11.  SG> would I write  code to do that?
  12.  
  13.  SG> Now picture this, I no longer have a screen, but a grid that works
  14.  SG> along the same principles as the screen did, except the points range
  15.  SG> from -20 to +20 on (x,y,z).  (That gives me a total of 68,921 (41^3)
  16.  SG> possible co-ordinates.)
  17.  SG> Pretend that Is a universe in space.  I'm in a tiny escape pod and
  18.  SG> must get from co-ordinate (-10,+05,+12) to co-ordinate (+07,+02,-11)
  19.  
  20. If you want to create an actual space, try :
  21. }
  22.  
  23. UNIT space;
  24. { Author: John Howard }
  25. {
  26. Define a two-dimensional space representation which is used for Cartesian and
  27. Polar coordinate systems.  A three-dimensional space is for Spherical and
  28. Azimuth-Elevation coordinate systems.
  29. }
  30. { A vector is a one-dimensional array of real numbers.  A matrix has two
  31.   dimensions m by n with m rows and n columns.  Notice the row number always
  32.   comes first in the dimensions and the indices.  Example square matrix A33 =
  33.              [ a11  a12  a13 ]    or generally  A[i, j]; i=rows, j=columns.
  34.              [ a21  a22  a23 ]
  35.              [ a31  a32  a33 ]
  36.   A matrix can be operated upon with appropriate column or row vectors.
  37. }
  38. INTERFACE
  39. {.$DEFINE D2}                            {remove period to use 2D}
  40. {$IFNDEF D2}
  41. const N = 3;                             { Cardinality for Three_Vector}
  42.       M = 3;                             { Square matrix for invert routine}
  43. {$ELSE}
  44. const N = 2;                             { Cardinality for Two_Vector}
  45.       M = 2;                             { Square matrix for invert routine}
  46. {$ENDIF}
  47.    Size = M;
  48. type
  49.    Vector = array [1..N] of real;        { 3D vector is the most common! }
  50.    Matrix = array [1..M, 1..N] of real;  { 3x3 matrix is the most common! }
  51.  
  52. {Store all the components into a vector}
  53. {$IFNDEF D2}
  54.    procedure Set_Value( var a: Vector; x_value, y_value, z_value: real);
  55. {$ELSE}
  56.    procedure Set_Value( var a: Vector; x_value, y_value: real);
  57. {$ENDIF}
  58.  
  59. {Retrieve the value of s from the ith element of a vector}
  60.    function Element( var a: Vector; i: integer): real;
  61.  
  62. {Retrieve the first element from a vector}
  63.    function  X_Component( var a: Vector): real;
  64.  
  65. {Retrieve the second element from a vector}
  66.    function  Y_Component( var a: Vector): real;
  67.  
  68. {Retrieve the third element from a vector}
  69. {$IFNDEF D2}
  70.    function  Z_Component( var a: Vector): real;
  71. {$ENDIF}
  72.  
  73. IMPLEMENTATION
  74.  
  75. procedure Set_Value;          { Note: parameter list intentionally left off}
  76. begin
  77.       a[1] := x_value;
  78.       a[2] := y_value;
  79. {$IFNDEF D2}
  80.       a[3] := z_value;
  81. {$ENDIF}
  82. end;
  83.  
  84. function Element( var a: Vector; i: integer): real;
  85. begin
  86.       Element := a[i];
  87. end;
  88.  
  89. function  X_Component( var a: Vector): real;
  90. begin
  91.       X_Component := a[1];
  92. end;
  93.  
  94. function  Y_Component( var a: Vector): real;
  95. begin
  96.       Y_Component := a[2];
  97. end;
  98.  
  99. {$IFNDEF D2}
  100. function  Z_Component( var a: Vector): real;
  101. begin
  102.       Z_Component := a[3];
  103. end;
  104. {$ENDIF}
  105. BEGIN
  106. END.
  107.  
  108. (**********
  109. If you do not want to create an actual 3d space, just convert coordinates :
  110.  
  111. You could use a two dimensional X_Component and Y_Component calculation to get
  112. you to an approximate region based upon Z_Component.  Example:
  113.  
  114. From point A(x1,y1) to B(x2,y2) you travel a distance = sqrt(sqr(x2-x1) +
  115.   sqr(y2-y1)) at a slope of (y2-y1)/(x2-x1).  That slope is called the Tangent
  116. of the angle of inclination of the line AB.
  117.  
  118. Now that you know where you are heading and how far away it is you can divide
  119. the total distance into sections say of unit length.  That means a distance of
  120. 10 would have ten units.  Every time your spaceship moves one unit in the known
  121. direction you can reverse the calculation to find out where you are at.  When
  122. you reach the final distance, you'd take approximations using the third
  123. component.  This idea is simple but not very accurate in the interum space.
  124.  
  125. You can use the same idea but implement it with a proper coordinate conversion.
  126. **********)
  127.  
  128. UNIT coord;
  129. { Author: John Howard }
  130. { Original source: Jack Crenshaw, 1992 Embedded Systems Programming }
  131. { Space Conversion -- Angles are capitalized }
  132. { All axes are perpendicular to each other }
  133. INTERFACE
  134. const
  135.       Zero = 0.0;
  136.       One  = 1.0;
  137.       TwoPi               = Two * SYSTEM.Pi;
  138.       Pi_Over_Two         = SYSTEM.Pi/Two;
  139.  
  140. { 1 binary angular measure = 1 pirad = Pi radians = 180 degrees }
  141.       Degrees_Per_Radian  = 180.0/SYSTEM.Pi;
  142.       Radians_Per_Degree  = SYSTEM.Pi/180.0;
  143.  
  144. { X-axis points east, y-axis north, and angle Theta is the heading measured
  145.   north of due east.  If Theta is zero that corresponds to a line running
  146.   along the x-axis a radial distance of r.
  147. }
  148. Procedure To_Polar ( x, y: real; Var r, Theta: real);
  149. Procedure From_Polar ( r, Theta: real; Var x, y: real);
  150.  
  151. { X-axis points toward you, y-axis right, z-axis upward, angle Phi measures
  152.   directions in the horizontal (x-y plane) from the x-axis, and angle Theta
  153.   measures the direction in the vertical from the z-axis downward.  If Theta
  154.   is zero that corresponds to a line pointed up the z-axis.
  155. }
  156. Procedure To_Spherical ( x, y, z: real; Var r, Phi, Theta: real);
  157. Procedure From_Spherical ( r, Phi, Theta: real; Var x, y, z: real);
  158.  
  159. { X-axis points east, y-axis north, z-axis upward, angle Phi corresponds to an
  160.   azimuth measured clockwise from due north, and angle Theta is the elevation
  161.   measured upwards from the horizon (x-y plane).
  162. }
  163. Procedure To_Azimuth_Elevation ( x, y, z: real; Var r, Phi, Theta: real);
  164. Procedure From_Azimuth_Elevation ( r, Phi, Theta: real; Var x, y, z: real);
  165.  
  166. Function Sign ( x, y: real): real;
  167. Function Degrees ( A: real): real;
  168. Function Radians ( A: real): real;
  169.  
  170. Function Atan ( x: real): real;           {ArcTangent}
  171. Function Atan2 ( s, c: real): real;
  172.  
  173. IMPLEMENTATION
  174.  
  175. { Convert from Cartesian to polar coordinates }
  176. Procedure To_Polar ( x, y: real; Var r, Theta: real);
  177. Begin
  178.   r := Sqrt(Sqr(x) + Sqr(y));
  179.   Theta := Atan2(y, x);
  180. End;
  181.  
  182. { Convert from polar to Cartesian coordinates }
  183. Procedure From_Polar ( r, Theta: real; Var x, y: real);
  184. Begin
  185.   x := r * Cos(Theta);
  186.   y := r * Sin(Theta);
  187. End;
  188.  
  189. { Convert from Cartesian to spherical polar coordinates }
  190. Procedure To_Spherical ( x, y, z: real; Var r, Phi, Theta: real);
  191. var  temp: real;
  192. Begin
  193.   To_Polar(x, y, temp, Phi);
  194.   To_Polar(z, temp, r, Theta);
  195. End;
  196.  
  197. { Convert from spherical polar to Cartesian coordinates }
  198. Procedure From_Spherical ( r, Phi, Theta: real; Var x, y, z: real);
  199. var  temp: real;
  200. Begin
  201.   From_Polar(r, Theta, z, temp);
  202.   From_Polar(temp, Phi, x, y);
  203. End;
  204.  
  205. { Convert from Cartesian to Az-El coordinates }
  206. Procedure To_Azimuth_Elevation ( x, y, z: real; Var r, Phi, Theta: real);
  207. var  temp: real;
  208. Begin
  209.   To_Polar(y, x, temp, Phi);
  210.   To_Polar(temp, z, r, Theta);
  211. End;
  212.  
  213. { Convert from Az-El to Cartesian coordinates }
  214. Procedure From_Azimuth_Elevation ( r, Phi, Theta: real; Var x, y, z: real);
  215. var  temp: real;
  216. Begin
  217.   From_Polar(r, Theta, temp, z);
  218.   From_Polar(temp, Phi, y, x);
  219. End;
  220.  
  221. { Returns Absolute value of x with Sign of y }
  222. Function Sign ( x, y: real): real;
  223. Begin
  224.   if y >= Zero then
  225.      Sign := Abs(x)
  226.   else
  227.      Sign := -Abs(x);
  228. End;
  229.  
  230. { Convert angle from radians to degrees }
  231. Function Degrees ( A: real): real;
  232. Begin
  233.   Degrees := Degrees_Per_Radian * A;
  234. End;
  235.  
  236. { Convert angle from degrees to radians }
  237. Function Radians ( A: real): real;
  238. Begin
  239.   Radians := Radians_Per_Degree * A;
  240. End;
  241.  
  242. { Inverse Trigonometric Tangent Function }
  243. Function Atan ( x: real): real;
  244. {  Arctangent algorithm uses fifth-order rational fraction with optimized
  245.    coefficients
  246. }
  247.    function _Atan ( x: real): real;
  248.    const
  249.      a = 0.999999447;
  250.      b = 0.259455937;
  251.      c = 0.592716128;
  252.  
  253.    var  y: real;
  254.    begin
  255.       y := x*x;
  256.       _Atan := a*x*( One + b*y) / ( One + c*y);
  257.    end;
  258.  
  259. var  a, y: real;
  260. Begin
  261.   y := Abs(x);
  262.   if y <= One then
  263.     a := _Atan(y)
  264.   else
  265.     a := Pi_Over_Two - _Atan( One / y);
  266.   if x <= Zero then
  267.     a := -a;
  268.   Atan := a;
  269. End;
  270.  
  271. { Four-Quadrant Inverse Trigonometric Tangent Function }
  272. Function Atan2 ( s, c: real): real;
  273. var  s1, c1, Theta: real;
  274. Begin
  275.   s1 := Abs(s);
  276.   c1 := Abs(c);
  277.   if c1 + s1 = Zero then
  278.     Theta := Zero
  279.   else if s1 <= c1 then
  280.          Theta := ArcTan(s1 / c1)
  281.        else
  282.          Theta := Pi_Over_Two - ArcTan(c1 / s1);
  283.   if c < Zero then
  284.     Theta := Pi - Theta;
  285.   Atan2 := Sign(Theta, s);
  286. End;
  287. BEGIN
  288. END.
  289. (*****END*****)
  290.